﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using System.Xml.Serialization;
using Pixysoft.Framework.Reflection.Controller;

namespace Pixysoft.Framework.Reflection
{
    class EmitHelper
    {
        public static void CreateInterfaceAttributes(Type targetType, TypeBuilder typeBuilder)
        {
            foreach (CustomAttributeData attributeData in CustomAttributeData.GetCustomAttributes(targetType))
            {
                List<object> paraList = new List<object>();

                foreach (CustomAttributeTypedArgument arg in attributeData.ConstructorArguments)
                {
                    paraList.Add(arg.Value);
                }

                CustomAttributeBuilder attrBuilder = new CustomAttributeBuilder(attributeData.Constructor, paraList.ToArray());

                typeBuilder.SetCustomAttribute(attrBuilder);
            }
        }

        public static void CreateSerializableAttribute(Type targetType, TypeBuilder typeBuilder)
        {
            if (!Pixysoft.Reflection.ReflectHelper.Instance.HasAttribute(targetType, typeof(SerializableAttribute)))
            {
                CustomAttributeBuilder serializeBuilder = new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyTypes), new object[] { });

                typeBuilder.SetCustomAttribute(serializeBuilder);
            }
        }

        public static void CreateXmlRootAttribute(Type targetType, TypeBuilder typeBuilder)
        {
            if (!Pixysoft.Reflection.ReflectHelper.Instance.HasAttribute(targetType, typeof(XmlRootAttribute)))
            {
                CustomAttributeBuilder xmlElementAttribute = new CustomAttributeBuilder(
                               typeof(XmlRootAttribute).GetConstructor(new Type[] { typeof(string) }),
                               new object[] { targetType.Name });

                typeBuilder.SetCustomAttribute(xmlElementAttribute);
            }
        }



        public static void CreateCloneMethod(TypeBuilder typeBuilder)
        {
            ConstructorBuilder ctor =
       typeBuilder.DefineDefaultConstructor(MethodAttributes.PrivateScope |
                MethodAttributes.Public | MethodAttributes.HideBySig |
                MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

            MethodAttributes attribute =
                    MethodAttributes.Public |
                    MethodAttributes.FamANDAssem |
                    MethodAttributes.Family |
                    MethodAttributes.Virtual |
                    MethodAttributes.HideBySig |
                    MethodAttributes.SpecialName;

            MethodBuilder setMethod = typeBuilder.DefineMethod("Clone", attribute, typeof(object), Type.EmptyTypes);
            ILGenerator setIl = setMethod.GetILGenerator();
            OpCodesFactory.CreateObject(setIl, ctor);
            OpCodesFactory.ReturnMethod(setIl);
        }
    }
}
